टाइपस्क्रिप्ट के साथ मजबूत Node.js फ़ाइल ऑपरेशंस को अनलॉक करें। यह व्यापक गाइड वैश्विक टीमों के लिए टाइप सुरक्षा, त्रुटि प्रबंधन और सर्वोत्तम प्रथाओं पर जोर देता है।
टाइपस्क्रिप्ट फ़ाइल सिस्टम मास्टरी: वैश्विक डेवलपर्स के लिए टाइप सुरक्षा के साथ Node.js फ़ाइल ऑपरेशंस
आधुनिक सॉफ्टवेयर डेवलपमेंट के विशाल परिदृश्य में, स्केलेबल सर्वर-साइड एप्लिकेशन, कमांड-लाइन टूल और बहुत कुछ बनाने के लिए Node.js एक शक्तिशाली रनटाइम के रूप में खड़ा है। कई Node.js एप्लिकेशनों का एक मूलभूत पहलू फ़ाइल सिस्टम के साथ इंटरैक्ट करना है - फ़ाइलों और डायरेक्टरीज़ को पढ़ना, लिखना, बनाना और प्रबंधित करना। जबकि जावास्क्रिप्ट इन ऑपरेशंस को संभालने के लिए लचीलापन प्रदान करता है, टाइपस्क्रिप्ट का परिचय स्थिर टाइप-चेकिंग, बेहतर टूलिंग और अंततः, आपके फ़ाइल सिस्टम कोड में अधिक विश्वसनीयता और रखरखाव क्षमता लाकर इस अनुभव को बढ़ाता है।
यह व्यापक गाइड डेवलपर्स के वैश्विक दर्शकों के लिए तैयार किया गया है, चाहे उनकी सांस्कृतिक पृष्ठभूमि या भौगोलिक स्थान कुछ भी हो, जो टाइपस्क्रिप्ट द्वारा प्रदान की जाने वाली मजबूती के साथ Node.js फ़ाइल ऑपरेशंस में महारत हासिल करना चाहते हैं। हम कोर `fs` मॉड्यूल में गहराई से उतरेंगे, इसके विभिन्न सिंक्रोनस और एसिंक्रोनस प्रतिमानों का पता लगाएंगे, आधुनिक प्रॉमिस-आधारित एपीआई की जांच करेंगे, और यह उजागर करेंगे कि टाइपस्क्रिप्ट का टाइप सिस्टम सामान्य त्रुटियों को कैसे कम कर सकता है और आपके कोड की स्पष्टता में सुधार कर सकता है।
आधारशिला: Node.js फ़ाइल सिस्टम (`fs`) को समझना
Node.js `fs` मॉड्यूल फ़ाइल सिस्टम के साथ इंटरैक्ट करने के लिए एक एपीआई प्रदान करता है जो मानक POSIX फ़ंक्शंस पर आधारित है। यह बुनियादी फ़ाइल पढ़ने और लिखने से लेकर जटिल डायरेक्टरी हेरफेर और फ़ाइल देखने तक, तरीकों की एक विस्तृत श्रृंखला प्रदान करता है। परंपरागत रूप से, इन ऑपरेशंस को कॉलबैक के साथ संभाला जाता था, जिससे जटिल परिदृश्यों में कुख्यात "कॉलबैक हेल" होता था। Node.js के विकास के साथ, प्रॉमिस और `async/await` एसिंक्रोनस ऑपरेशंस के लिए पसंदीदा पैटर्न के रूप में उभरे हैं, जिससे कोड अधिक पठनीय और प्रबंधनीय हो गया है।
फ़ाइल सिस्टम ऑपरेशंस के लिए टाइपस्क्रिप्ट क्यों?
जबकि Node.js का `fs` मॉड्यूल सादे जावास्क्रिप्ट के साथ पूरी तरह से काम करता है, टाइपस्क्रिप्ट को एकीकृत करने से कई आकर्षक फायदे मिलते हैं:
- टाइप सुरक्षा: कंपाइल समय पर गलत आर्गुमेंट प्रकारों, लापता मापदंडों या अप्रत्याशित रिटर्न मानों जैसी सामान्य त्रुटियों को पकड़ता है, इससे पहले कि आपका कोड चले। यह अमूल्य है, खासकर जब विभिन्न फ़ाइल एन्कोडिंग, फ़्लैग और `Buffer` ऑब्जेक्ट्स से निपटते हैं।
- बेहतर पठनीयता: स्पष्ट टाइप एनोटेशन यह स्पष्ट करते हैं कि एक फ़ंक्शन किस प्रकार के डेटा की अपेक्षा करता है और वह क्या लौटाएगा, जिससे विविध टीमों में डेवलपर्स के लिए कोड की समझ में सुधार होता है।
- बेहतर टूलिंग और ऑटो-कंप्लीशन: आईडीई (जैसे VS कोड) टाइपस्क्रिप्ट की टाइप परिभाषाओं का लाभ उठाते हुए इंटेलिजेंट ऑटो-कंप्लीशन, पैरामीटर संकेत और इनलाइन दस्तावेज़ प्रदान करते हैं, जिससे उत्पादकता में उल्लेखनीय वृद्धि होती है।
- रिफैक्टरिंग आत्मविश्वास: जब आप एक इंटरफ़ेस या फ़ंक्शन सिग्नेचर बदलते हैं, तो टाइपस्क्रिप्ट तुरंत सभी प्रभावित क्षेत्रों को चिह्नित करता है, जिससे बड़े पैमाने पर रिफैक्टरिंग कम त्रुटि-प्रवण होती है।
- वैश्विक स्थिरता: अंतरराष्ट्रीय विकास टीमों में एक सुसंगत कोडिंग शैली और डेटा संरचनाओं की समझ सुनिश्चित करता है, जिससे अस्पष्टता कम होती है।
सिंक्रोनस बनाम एसिंक्रोनस ऑपरेशंस: एक वैश्विक परिप्रेक्ष्य
सिंक्रोनस और एसिंक्रोनस ऑपरेशंस के बीच अंतर को समझना महत्वपूर्ण है, खासकर जब वैश्विक तैनाती के लिए एप्लिकेशन बनाते हैं जहां प्रदर्शन और प्रतिक्रियाशीलता सर्वोपरि है। अधिकांश `fs` मॉड्यूल फ़ंक्शंस सिंक्रोनस और एसिंक्रोनस दोनों फ्लेवर में आते हैं। अंगूठे के नियम के रूप में, Node.js सर्वर की प्रतिक्रियाशीलता बनाए रखने के लिए गैर-अवरुद्ध I/O ऑपरेशंस के लिए एसिंक्रोनस विधियों को प्राथमिकता दी जाती है।
- एसिंक्रोनस (गैर-अवरुद्ध): ये विधियाँ अपने अंतिम आर्गुमेंट के रूप में एक कॉलबैक फ़ंक्शन लेती हैं या एक `Promise` लौटाती हैं। वे फ़ाइल सिस्टम ऑपरेशन शुरू करती हैं और तुरंत वापस लौट जाती हैं, जिससे अन्य कोड को निष्पादित करने की अनुमति मिलती है। जब ऑपरेशन पूरा हो जाता है, तो कॉलबैक को इन्वोक किया जाता है (या प्रॉमिस रिज़ॉल्व/रिजेक्ट होता है)। यह सर्वर एप्लिकेशनों के लिए आदर्श है जो दुनिया भर के उपयोगकर्ताओं से कई समवर्ती अनुरोधों को संभालते हैं, क्योंकि यह फ़ाइल ऑपरेशन के समाप्त होने की प्रतीक्षा करते समय सर्वर को फ्रीज़ होने से रोकता है।
- सिंक्रोनस (अवरुद्ध): ये विधियाँ ऑपरेशन को पूरी तरह से पूरा करने से पहले निष्पादित करती हैं। हालांकि कोड करने में सरल, वे Node.js इवेंट लूप को ब्लॉक करते हैं, जिससे फ़ाइल सिस्टम ऑपरेशन पूरा होने तक किसी भी अन्य कोड को चलने से रोका जा सकता है। इससे महत्वपूर्ण प्रदर्शन बाधाएं और अनुत्तरदायी एप्लिकेशन हो सकते हैं, खासकर उच्च-ट्रैफ़िक वातावरण में। इनका उपयोग संयम से करें, आमतौर पर एप्लिकेशन स्टार्टअप लॉजिक या सरल स्क्रिप्ट के लिए जहां अवरुद्ध करना स्वीकार्य है।
टाइपस्क्रिप्ट में कोर फ़ाइल ऑपरेशन प्रकार
आइए आम फ़ाइल सिस्टम ऑपरेशंस के साथ टाइपस्क्रिप्ट के व्यावहारिक अनुप्रयोग में गोता लगाएँ। हम Node.js के लिए अंतर्निहित टाइप परिभाषाओं का उपयोग करेंगे, जो आमतौर पर `@types/node` पैकेज के माध्यम से उपलब्ध होते हैं।
शुरू करने के लिए, सुनिश्चित करें कि आपके प्रोजेक्ट में टाइपस्क्रिप्ट और Node.js प्रकार स्थापित हैं:
npm install typescript @types/node --save-dev
आपकी `tsconfig.json` को तदनुसार कॉन्फ़िगर किया जाना चाहिए, उदाहरण के लिए:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
फ़ाइलें पढ़ना: `readFile`, `readFileSync`, और प्रॉमिसेस एपीआई
फ़ाइलों से सामग्री पढ़ना एक मूलभूत ऑपरेशन है। टाइपस्क्रिप्ट यह सुनिश्चित करने में मदद करता है कि आप फ़ाइल पाथ, एन्कोडिंग और संभावित त्रुटियों को सही ढंग से संभालते हैं।
एसिंक्रोनस फ़ाइल रीड (कॉलबैक-आधारित)
`fs.readFile` एसिंक्रोनस फ़ाइल पढ़ने के लिए कार्यसाधक है। यह पाथ, एक वैकल्पिक एन्कोडिंग और एक कॉलबैक फ़ंक्शन लेता है। टाइपस्क्रिप्ट यह सुनिश्चित करता है कि कॉलबैक के आर्गुमेंट्स सही ढंग से टाइप किए गए हों (`Error | null`, `Buffer | string`)।
import * as fs from 'fs';
const filePath: string = 'data/example.txt';
fs.readFile(filePath, 'utf8', (err: NodeJS.ErrnoException | null, data: string) => {
if (err) {
// अंतरराष्ट्रीय डीबगिंग के लिए त्रुटि लॉग करें, उदा. 'फ़ाइल नहीं मिली'
console.error(`फ़ाइल '\''${filePath}'\'' पढ़ने में त्रुटि: ${err.message}`);
return;
}
// फ़ाइल सामग्री को संसाधित करें, 'utf8' एन्कोडिंग के अनुसार यह सुनिश्चित करें कि यह एक स्ट्रिंग है
console.log(`फ़ाइल सामग्री (${filePath}):\n${data}`);
});
// उदाहरण: बाइनरी डेटा पढ़ना (कोई एन्कोडिंग निर्दिष्ट नहीं)
const binaryFilePath: string = 'data/image.png';
fs.readFile(binaryFilePath, (err: NodeJS.ErrnoException | null, data: Buffer) => {
if (err) {
console.error(`बाइनरी फ़ाइल '\''${binaryFilePath}'\'' पढ़ने में त्रुटि: ${err.message}`);
return;
}
// 'डेटा' यहां एक बफ़र है, आगे की प्रोसेसिंग के लिए तैयार है (उदा. क्लाइंट को स्ट्रीमिंग)
console.log(`${binaryFilePath} से ${data.byteLength} बाइट्स पढ़े`);
});
सिंक्रोनस फ़ाइल रीड
`fs.readFileSync` इवेंट लूप को ब्लॉक करता है। इसका रिटर्न टाइप `Buffer` या `string` होता है, यह इस बात पर निर्भर करता है कि कोई एन्कोडिंग प्रदान की गई है या नहीं। टाइपस्क्रिप्ट इसे सही ढंग से अनुमानित करता है।
import * as fs from 'fs';
const syncFilePath: string = 'data/sync_example.txt';
try {
const content: string = fs.readFileSync(syncFilePath, 'utf8');
console.log(`सिंक्रोनस रूप से पढ़ी गई सामग्री (${syncFilePath}):\n${content}`);
} catch (error: any) {
console.error(`'\''${syncFilePath}'\'' के लिए सिंक्रोनस रीड त्रुटि: ${error.message}`);
}
प्रॉमिस-आधारित फ़ाइल रीड (`fs/promises`)
आधुनिक `fs/promises` एपीआई एक क्लीनर, प्रॉमिस-आधारित इंटरफ़ेस प्रदान करता है, जिसे एसिंक्रोनस ऑपरेशंस के लिए अत्यधिक अनुशंसित किया जाता है। टाइपस्क्रिप्ट यहां उत्कृष्ट है, खासकर `async/await` के साथ।
import * as fsPromises from 'fs/promises';
async function readTextFile(path: string): Promise
फ़ाइलें लिखना: `writeFile`, `writeFileSync`, और फ़्लैग
फ़ाइलों में डेटा लिखना भी उतना ही महत्वपूर्ण है। टाइपस्क्रिप्ट फ़ाइल पाथ, डेटा प्रकार (स्ट्रिंग या बफ़र), एन्कोडिंग और फ़ाइल ओपन फ़्लैग्स को प्रबंधित करने में मदद करता है।
एसिंक्रोनस फ़ाइल राइट
`fs.writeFile` का उपयोग फ़ाइल में डेटा लिखने के लिए किया जाता है, यदि फ़ाइल पहले से मौजूद है तो वह डिफ़ॉल्ट रूप से उसे बदल देता है। आप `flags` के साथ इस व्यवहार को नियंत्रित कर सकते हैं।
import * as fs from 'fs';
const outputFilePath: string = 'data/output.txt';
const fileContent: string = 'यह टाइपस्क्रिप्ट द्वारा लिखी गई नई सामग्री है।';
fs.writeFile(outputFilePath, fileContent, 'utf8', (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`फ़ाइल '\''${outputFilePath}'\'' लिखने में त्रुटि: ${err.message}`);
return;
}
console.log(`फ़ाइल '\''${outputFilePath}'\'' सफलतापूर्वक लिखी गई।`);
});
// बफ़र डेटा के साथ उदाहरण
const bufferContent: Buffer = Buffer.from('बाइनरी डेटा उदाहरण');
const binaryOutputFilePath: string = 'data/binary_output.bin';
fs.writeFile(binaryOutputFilePath, bufferContent, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`बाइनरी फ़ाइल '\''${binaryOutputFilePath}'\'' लिखने में त्रुटि: ${err.message}`);
return;
}
console.log(`बाइनरी फ़ाइल '\''${binaryOutputFilePath}'\'' सफलतापूर्वक लिखी गई।`);
});
सिंक्रोनस फ़ाइल राइट
`fs.writeFileSync` इवेंट लूप को तब तक ब्लॉक करता है जब तक लिखने का ऑपरेशन पूरा नहीं हो जाता।
import * as fs from 'fs';
const syncOutputFilePath: string = 'data/sync_output.txt';
try {
fs.writeFileSync(syncOutputFilePath, 'सिंक्रोनस रूप से लिखी गई सामग्री।', 'utf8');
console.log(`फ़ाइल '\''${syncOutputFilePath}'\'' सिंक्रोनस रूप से लिखी गई।`);
} catch (error: any) {
console.error(`'\''${syncOutputFilePath}'\'' के लिए सिंक्रोनस राइट त्रुटि: ${error.message}`);
}
प्रॉमिस-आधारित फ़ाइल राइट (`fs/promises`)
`async/await` और `fs/promises` के साथ आधुनिक दृष्टिकोण अक्सर एसिंक्रोनस राइट्स के प्रबंधन के लिए क्लीनर होता है।
import * as fsPromises from 'fs/promises';
import { constants as fsConstants } from 'fs'; // फ़्लैग के लिए
async function writeDataToFile(path: string, data: string | Buffer): Promise
महत्वपूर्ण फ़्लैग:
- `'w'` (डिफ़ॉल्ट): लिखने के लिए फ़ाइल खोलें। फ़ाइल बनाई जाती है (यदि वह मौजूद नहीं है) या ट्रंकेट की जाती है (यदि वह मौजूद है)।
- `'w+'`: पढ़ने और लिखने के लिए फ़ाइल खोलें। फ़ाइल बनाई जाती है (यदि वह मौजूद नहीं है) या ट्रंकेट की जाती है (यदि वह मौजूद है)।
- `'a'` (जोड़ें): जोड़ने के लिए फ़ाइल खोलें। यदि फ़ाइल मौजूद नहीं है तो वह बनाई जाती है।
- `'a+'`: पढ़ने और जोड़ने के लिए फ़ाइल खोलें। यदि फ़ाइल मौजूद नहीं है तो वह बनाई जाती है।
- `'r'` (पढ़ें): पढ़ने के लिए फ़ाइल खोलें। यदि फ़ाइल मौजूद नहीं है तो एक अपवाद उत्पन्न होता है।
- `'r+'`: पढ़ने और लिखने के लिए फ़ाइल खोलें। यदि फ़ाइल मौजूद नहीं है तो एक अपवाद उत्पन्न होता है।
- `'wx'` (एक्सक्लूसिव राइट): `'w'` की तरह लेकिन यदि पाथ मौजूद है तो विफल हो जाता है।
- `'ax'` (एक्सक्लूसिव अपेंड): `'a'` की तरह लेकिन यदि पाथ मौजूद है तो विफल हो जाता है।
फ़ाइलों में जोड़ना: `appendFile`, `appendFileSync`
जब आपको मौजूदा फ़ाइल की सामग्री को ओवरराइट किए बिना उसके अंत में डेटा जोड़ने की आवश्यकता होती है, तो `appendFile` आपकी पसंद है। यह विशेष रूप से लॉगिंग, डेटा संग्रह या ऑडिट ट्रेल्स के लिए उपयोगी है।
एसिंक्रोनस अपेंड
import * as fs from 'fs';
const logFilePath: string = 'data/app_logs.log';
function logMessage(message: string): void {
const timestamp: string = new Date().toISOString();
const logEntry: string = `${timestamp} - ${message}\n`;
fs.appendFile(logFilePath, logEntry, 'utf8', (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`लॉग फ़ाइल '\''${logFilePath}'\'' में जोड़ने में त्रुटि: ${err.message}`);
return;
}
console.log(`संदेश को '\''${logFilePath}'\'' में लॉग किया गया।`);
});
}
logMessage('उपयोगकर्ता "एलिस" ने लॉग इन किया।');
setTimeout(() => logMessage('सिस्टम अपडेट शुरू किया गया।'), 50);
logMessage('डेटाबेस कनेक्शन स्थापित किया गया।');
सिंक्रोनस अपेंड
import * as fs from 'fs';
const syncLogFilePath: string = 'data/sync_app_logs.log';
function logMessageSync(message: string): void {
const timestamp: string = new Date().toISOString();
const logEntry: string = `${timestamp} - ${message}\n`;
try {
fs.appendFileSync(syncLogFilePath, logEntry, 'utf8');
console.log(`संदेश को सिंक्रोनस रूप से '\''${syncLogFilePath}'\'' में लॉग किया गया।`);
} catch (error: any) {
console.error(`लॉग फ़ाइल '\''${syncLogFilePath}'\'' में जोड़ने में सिंक्रोनस त्रुटि: ${error.message}`);
}
}
logMessageSync('एप्लिकेशन शुरू हुआ।');
logMessageSync('कॉन्फ़िगरेशन लोड हुआ।');
प्रॉमिस-आधारित अपेंड (`fs/promises`)
import * as fsPromises from 'fs/promises';
const promiseLogFilePath: string = 'data/promise_app_logs.log';
async function logMessagePromise(message: string): Promise
फ़ाइलें हटाना: `unlink`, `unlinkSync`
फ़ाइल सिस्टम से फ़ाइलों को हटाना। टाइपस्क्रिप्ट यह सुनिश्चित करने में मदद करता है कि आप एक वैध पाथ पास कर रहे हैं और त्रुटियों को सही ढंग से संभाल रहे हैं।
एसिंक्रोनस डिलीट
import * as fs from 'fs';
const fileToDeletePath: string = 'data/temp_to_delete.txt';
// सबसे पहले, यह सुनिश्चित करने के लिए फ़ाइल बनाएँ कि यह विलोपन डेमो के लिए मौजूद है
fs.writeFile(fileToDeletePath, 'अस्थायी सामग्री।', 'utf8', (err) => {
if (err) {
console.error('विलोपन डेमो के लिए फ़ाइल बनाने में त्रुटि:', err);
return;
}
console.log(`फ़ाइल '\''${fileToDeletePath}'\'' विलोपन डेमो के लिए बनाई गई।`);
fs.unlink(fileToDeletePath, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`फ़ाइल '\''${fileToDeletePath}'\'' हटाने में त्रुटि: ${err.message}`);
return;
}
console.log(`फ़ाइल '\''${fileToDeletePath}'\'' सफलतापूर्वक हटाई गई।`);
});
});
सिंक्रोनस डिलीट
import * as fs from 'fs';
const syncFileToDeletePath: string = 'data/sync_temp_to_delete.txt';
try {
fs.writeFileSync(syncFileToDeletePath, 'सिंक अस्थायी सामग्री।', 'utf8');
console.log(`फ़ाइल '\''${syncFileToDeletePath}'\'' बनाई गई।`);
fs.unlinkSync(syncFileToDeletePath);
console.log(`फ़ाइल '\''${syncFileToDeletePath}'\'' सिंक्रोनस रूप से हटाई गई।`);
} catch (error: any) {
console.error(`'\''${syncFileToDeletePath}'\'' के लिए सिंक्रोनस विलोपन त्रुटि: ${error.message}`);
}
प्रॉमिस-आधारित डिलीट (`fs/promises`)
import * as fsPromises from 'fs/promises';
const promiseFileToDeletePath: string = 'data/promise_temp_to_delete.txt';
async function deleteFile(path: string): Promise
फ़ाइल अस्तित्व और अनुमतियों की जाँच करना: `existsSync`, `access`, `accessSync`
किसी फ़ाइल पर कार्य करने से पहले, आपको यह जांचने की आवश्यकता हो सकती है कि वह मौजूद है या नहीं या वर्तमान प्रक्रिया के पास आवश्यक अनुमतियाँ हैं या नहीं। टाइपस्क्रिप्ट `mode` पैरामीटर के लिए प्रकार प्रदान करके सहायता करता है।
सिंक्रोनस अस्तित्व जाँच
`fs.existsSync` एक सरल, सिंक्रोनस जाँच है। हालांकि सुविधाजनक, इसमें एक दौड़ की स्थिति की भेद्यता है (एक फ़ाइल `existsSync` और बाद के ऑपरेशन के बीच हटाई जा सकती है), इसलिए महत्वपूर्ण ऑपरेशंस के लिए `fs.access` का उपयोग करना अक्सर बेहतर होता है।
import * as fs from 'fs';
const checkFilePath: string = 'data/example.txt';
if (fs.existsSync(checkFilePath)) {
console.log(`फ़ाइल '\''${checkFilePath}'\'' मौजूद है।`);
} else {
console.log(`फ़ाइल '\''${checkFilePath}'\'' मौजूद नहीं है।`);
}
एसिंक्रोनस अनुमति जाँच (`fs.access`)
`fs.access` `path` द्वारा निर्दिष्ट फ़ाइल या डायरेक्टरी के लिए उपयोगकर्ता की अनुमतियों का परीक्षण करता है। यह एसिंक्रोनस है और एक `mode` आर्गुमेंट लेता है (उदा. अस्तित्व के लिए `fs.constants.F_OK`, पढ़ने के लिए `R_OK`, लिखने के लिए `W_OK`, निष्पादन के लिए `X_OK`)।
import * as fs from 'fs';
import { constants } from 'fs';
const accessFilePath: string = 'data/example.txt';
fs.access(accessFilePath, constants.F_OK, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`फ़ाइल '\''${accessFilePath}'\'' मौजूद नहीं है या पहुँच अस्वीकृत है।`);
return;
}
console.log(`फ़ाइल '\''${accessFilePath}'\'' मौजूद है।`);
});
fs.access(accessFilePath, constants.R_OK | constants.W_OK, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`फ़ाइल '\''${accessFilePath}'\'' पठनीय/लेखनीय नहीं है या पहुँच अस्वीकृत है: ${err.message}`);
return;
}
console.log(`फ़ाइल '\''${accessFilePath}'\'' पठनीय और लेखनीय है।`);
});
प्रॉमिस-आधारित अनुमति जाँच (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { constants } from 'fs';
async function checkFilePermissions(path: string, mode: number): Promise
फ़ाइल जानकारी प्राप्त करना: `stat`, `statSync`, `fs.Stats`
`fs.stat` फ़ंक्शंस का परिवार एक फ़ाइल या डायरेक्टरी के बारे में विस्तृत जानकारी प्रदान करता है, जैसे आकार, निर्माण तिथि, संशोधन तिथि और अनुमतियाँ। टाइपस्क्रिप्ट का `fs.Stats` इंटरफ़ेस इस डेटा के साथ काम को अत्यधिक संरचित और विश्वसनीय बनाता है।
एसिंक्रोनस स्टेट
import * as fs from 'fs';
import { Stats } from 'fs';
const statFilePath: string = 'data/example.txt';
fs.stat(statFilePath, (err: NodeJS.ErrnoException | null, stats: Stats) => {
if (err) {
console.error(`'\''${statFilePath}'\'' के लिए स्टेट्स प्राप्त करने में त्रुटि: ${err.message}`);
return;
}
console.log(`'\''${statFilePath}'\'' के लिए स्टेट्स:`);
console.log(` फ़ाइल है: ${stats.isFile()}`);
console.log(` डायरेक्टरी है: ${stats.isDirectory()}`);
console.log(` आकार: ${stats.size} बाइट्स`);
console.log(` निर्माण समय: ${stats.birthtime.toISOString()}`);
console.log(` अंतिम संशोधित: ${stats.mtime.toISOString()}`);
});
प्रॉमिस-आधारित स्टेट (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { Stats } from 'fs'; // अभी भी 'fs' मॉड्यूल के Stats इंटरफ़ेस का उपयोग करें
async function getFileStats(path: string): Promise
टाइपस्क्रिप्ट के साथ डायरेक्टरी ऑपरेशंस
फ़ाइलों को व्यवस्थित करने, एप्लिकेशन-विशिष्ट स्टोरेज बनाने या अस्थायी डेटा को संभालने के लिए डायरेक्टरीज़ का प्रबंधन एक आम आवश्यकता है। टाइपस्क्रिप्ट इन ऑपरेशंस के लिए मजबूत टाइपिंग प्रदान करता है।
डायरेक्टरीज़ बनाना: `mkdir`, `mkdirSync`
नई डायरेक्टरीज़ बनाने के लिए `fs.mkdir` फ़ंक्शन का उपयोग किया जाता है। `recursive` विकल्प अविश्वसनीय रूप से उपयोगी है यदि वे पहले से मौजूद नहीं हैं, तो पैरेंट डायरेक्टरीज़ बनाने के लिए, यूनिक्स-जैसे सिस्टम में `mkdir -p` के व्यवहार की नकल करता है।
एसिंक्रोनस डायरेक्टरी क्रिएशन
import * as fs from 'fs';
const newDirPath: string = 'data/new_directory';
const recursiveDirPath: string = 'data/nested/path/to/create';
// एक सिंगल डायरेक्टरी बनाएँ
fs.mkdir(newDirPath, (err: NodeJS.ErrnoException | null) => {
if (err) {
// यदि डायरेक्टरी पहले से मौजूद है तो EEXIST त्रुटि को अनदेखा करें
if (err.code === 'EEXIST') {
console.log(`डायरेक्टरी '\''${newDirPath}'\'' पहले से मौजूद है।`);
} else {
console.error(`डायरेक्टरी '\''${newDirPath}'\'' बनाने में त्रुटि: ${err.message}`);
}
return;
}
console.log(`डायरेक्टरी '\''${newDirPath}'\'' सफलतापूर्वक बनाई गई।`);
});
// नेस्टेड डायरेक्टरीज़ को रिकर्सिव रूप से बनाएँ
fs.mkdir(recursiveDirPath, { recursive: true }, (err: NodeJS.ErrnoException | null) => {
if (err) {
if (err.code === 'EEXIST') {
console.log(`डायरेक्टरी '\''${recursiveDirPath}'\'' पहले से मौजूद है।`);
} else {
console.error(`रिकर्सिव डायरेक्टरी '\''${recursiveDirPath}'\'' बनाने में त्रुटि: ${err.message}`);
}
return;
}
console.log(`रिकर्सिव डायरेक्टरीज़ '\''${recursiveDirPath}'\'' सफलतापूर्वक बनाई गई।`);
});
प्रॉमिस-आधारित डायरेक्टरी क्रिएशन (`fs/promises`)
import * as fsPromises from 'fs/promises';
async function createDirectory(path: string, recursive: boolean = false): Promise
डायरेक्टरी सामग्री पढ़ना: `readdir`, `readdirSync`, `fs.Dirent`
किसी दी गई डायरेक्टरी के भीतर फ़ाइलों और उप-डायरेक्टरीज़ को सूचीबद्ध करने के लिए, आप `fs.readdir` का उपयोग करते हैं। `withFileTypes` विकल्प एक आधुनिक जोड़ है जो `fs.Dirent` ऑब्जेक्ट लौटाता है, प्रत्येक एंट्री को व्यक्तिगत रूप से `stat` किए बिना सीधे अधिक विस्तृत जानकारी प्रदान करता है।
एसिंक्रोनस डायरेक्टरी रीड
import * as fs from 'fs';
const readDirPath: string = 'data';
fs.readdir(readDirPath, (err: NodeJS.ErrnoException | null, files: string[]) => {
if (err) {
console.error(`डायरेक्टरी '\''${readDirPath}'\'' पढ़ने में त्रुटि: ${err.message}`);
return;
}
console.log(`डायरेक्टरी '\''${readDirPath}'\'' की सामग्री:`);
files.forEach(file => {
console.log(` - ${file}`);
});
});
// `withFileTypes` विकल्प के साथ
fs.readdir(readDirPath, { withFileTypes: true }, (err: NodeJS.ErrnoException | null, dirents: fs.Dirent[]) => {
if (err) {
console.error(`फ़ाइल प्रकारों के साथ डायरेक्टरी '\''${readDirPath}'\'' पढ़ने में त्रुटि: ${err.message}`);
return;
}
console.log(`डायरेक्टरी '\''${readDirPath}'\'' की सामग्री (प्रकारों के साथ):`);
dirents.forEach(dirent => {
const type: string = dirent.isFile() ? 'फ़ाइल' : dirent.isDirectory() ? 'डायरेक्टरी' : 'अन्य';
console.log(` - ${dirent.name} (${type})`);
});
});
प्रॉमिस-आधारित डायरेक्टरी रीड (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { Dirent } from 'fs'; // अभी भी 'fs' मॉड्यूल के Dirent इंटरफ़ेस का उपयोग करें
async function listDirectoryContents(path: string): Promise
डायरेक्टरीज़ हटाना: `rmdir` (अप्रचलित), `rm`, `rmSync`
Node.js ने अपने डायरेक्टरी विलोपन विधियों को विकसित किया है। रिकर्सिव विलोपन के लिए `fs.rmdir` को अब `fs.rm` ने बड़े पैमाने पर बदल दिया है, जो एक अधिक मजबूत और सुसंगत एपीआई प्रदान करता है।
एसिंक्रोनस डायरेक्टरी विलोपन (`fs.rm`)
`fs.rm` फ़ंक्शन (Node.js 14.14.0 के बाद से उपलब्ध) फ़ाइलों और डायरेक्टरीज़ को हटाने का अनुशंसित तरीका है। `recursive: true` विकल्प गैर-खाली डायरेक्टरीज़ को हटाने के लिए महत्वपूर्ण है।
import * as fs from 'fs';
const dirToDeletePath: string = 'data/dir_to_delete';
const nestedDirToDeletePath: string = 'data/nested_dir/sub';
// सेटअप: रिकर्सिव विलोपन डेमो के लिए अंदर एक फ़ाइल के साथ एक डायरेक्टरी बनाएँ
fs.mkdir(nestedDirToDeletePath, { recursive: true }, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('डेमो के लिए नेस्टेड डायरेक्टरी बनाने में त्रुटि:', err);
return;
}
fs.writeFile(`${nestedDirToDeletePath}/file_inside.txt`, 'कुछ सामग्री', (err) => {
if (err) { console.error('नेस्टेड डायरेक्टरी के अंदर फ़ाइल बनाने में त्रुटि:', err); return; }
console.log(`डायरेक्टरी '\''${nestedDirToDeletePath}'\'' और फ़ाइल विलोपन डेमो के लिए बनाई गई।`);
fs.rm(nestedDirToDeletePath, { recursive: true, force: true }, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`रिकर्सिव डायरेक्टरी '\''${nestedDirToDeletePath}'\'' हटाने में त्रुटि: ${err.message}`);
return;
}
console.log(`रिकर्सिव डायरेक्टरी '\''${nestedDirToDeletePath}'\'' सफलतापूर्वक हटाई गई।`);
});
});
});
// एक खाली डायरेक्टरी को हटाना
fs.mkdir(dirToDeletePath, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('डेमो के लिए खाली डायरेक्टरी बनाने में त्रुटि:', err);
return;
}
console.log(`डायरेक्टरी '\''${dirToDeletePath}'\'' विलोपन डेमो के लिए बनाई गई।`);
fs.rm(dirToDeletePath, { recursive: false }, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`खाली डायरेक्टरी '\''${dirToDeletePath}'\'' हटाने में त्रुटि: ${err.message}`);
return;
}
console.log(`खाली डायरेक्टरी '\''${dirToDeletePath}'\'' सफलतापूर्वक हटाई गई।`);
});
});
प्रॉमिस-आधारित डायरेक्टरी विलोपन (`fs/promises`)
import * as fsPromises from 'fs/promises';
async function deleteDirectory(path: string, recursive: boolean = false): Promise
टाइपस्क्रिप्ट के साथ उन्नत फ़ाइल सिस्टम अवधारणाएँ
बुनियादी पढ़ने/लिखने के ऑपरेशंस से परे, Node.js बड़ी फ़ाइलों, निरंतर डेटा प्रवाह और फ़ाइल सिस्टम की वास्तविक समय की निगरानी के लिए शक्तिशाली सुविधाएँ प्रदान करता है। टाइपस्क्रिप्ट की टाइप घोषणाएँ इन उन्नत परिदृश्यों तक आसानी से विस्तारित होती हैं, जिससे मजबूती सुनिश्चित होती है।
फ़ाइल डिस्क्रिप्टर और स्ट्रीम
बहुत बड़ी फ़ाइलों के लिए या जब आपको फ़ाइल एक्सेस पर ठीक नियंत्रण की आवश्यकता होती है (उदाहरण के लिए, फ़ाइल के भीतर विशिष्ट स्थितियाँ), तो फ़ाइल डिस्क्रिप्टर और स्ट्रीम आवश्यक हो जाते हैं। स्ट्रीम डेटा की बड़ी मात्रा को चंक्स में पढ़ने या लिखने को कुशलतापूर्वक संभालने का एक कुशल तरीका प्रदान करते हैं, बजाय इसके कि पूरी फ़ाइल को मेमोरी में लोड किया जाए, जो स्केलेबल एप्लिकेशनों और विश्व स्तर पर सर्वर पर कुशल संसाधन प्रबंधन के लिए महत्वपूर्ण है।
डिस्क्रिप्टर के साथ फ़ाइलें खोलना और बंद करना (`fs.open`, `fs.close`)
फ़ाइल डिस्क्रिप्टर ऑपरेटिंग सिस्टम द्वारा एक खुली फ़ाइल को असाइन किया गया एक अद्वितीय पहचानकर्ता (एक संख्या) है। आप फ़ाइल डिस्क्रिप्टर प्राप्त करने के लिए `fs.open` का उपयोग कर सकते हैं, फिर उस डिस्क्रिप्टर का उपयोग करके `fs.read` या `fs.write` जैसे ऑपरेशंस कर सकते हैं, और अंत में इसे `fs.close` कर सकते हैं।
import * as fs from 'fs';
import { promises as fsPromises } from 'fs';
import { constants } from 'fs';
const descriptorFilePath: string = 'data/descriptor_example.txt';
async function demonstrateFileDescriptorOperations(): Promise
फ़ाइल स्ट्रीम (`fs.createReadStream`, `fs.createWriteStream`)
स्ट्रीम बड़ी फ़ाइलों को कुशलतापूर्वक संभालने के लिए शक्तिशाली हैं। `fs.createReadStream` और `fs.createWriteStream` क्रमशः `Readable` और `Writable` स्ट्रीम लौटाते हैं, जो Node.js के स्ट्रीमिंग एपीआई के साथ सहजता से एकीकृत होते हैं। टाइपस्क्रिप्ट इन स्ट्रीम इवेंट्स (उदा. `'data'`, `'end'`, `'error'`) के लिए उत्कृष्ट टाइप परिभाषाएँ प्रदान करता है।
import * as fs from 'fs';
const largeFilePath: string = 'data/large_file.txt';
const copiedFilePath: string = 'data/copied_file.txt';
// प्रदर्शन के लिए एक डमी बड़ी फ़ाइल बनाएँ
function createLargeFile(path: string, sizeInMB: number): void {
const content: string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '; // 56 वर्ण
const stream = fs.createWriteStream(path);
const totalChars = sizeInMB * 1024 * 1024; // MB को बाइट्स में बदलें
const iterations = Math.ceil(totalChars / content.length);
for (let i = 0; i < iterations; i++) {
stream.write(content);
}
stream.end(() => console.log(`बड़ी फ़ाइल '\''${path}'\'' (${sizeInMB}MB) बनाई गई।`));
}
// प्रदर्शन के लिए, आइए पहले 'data' डायरेक्टरी मौजूद सुनिश्चित करें
fs.mkdir('data', { recursive: true }, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('डेटा डायरेक्टरी बनाने में त्रुटि:', err);
return;
}
createLargeFile(largeFilePath, 1); // एक 1MB फ़ाइल बनाएँ
});
// स्ट्रीम का उपयोग करके फ़ाइल कॉपी करें
function copyFileWithStreams(source: string, destination: string): void {
const readStream = fs.createReadStream(source);
const writeStream = fs.createWriteStream(destination);
readStream.on('open', () => console.log(`'\''${source}'\'' के लिए स्ट्रीम पढ़ रहा है खोला गया।`));
writeStream.on('open', () => console.log(`'\''${destination}'\'' के लिए स्ट्रीम लिख रहा है खोला गया।`));
// रीड स्ट्रीम से राइट स्ट्रीम में डेटा पाइप करें
readStream.pipe(writeStream);
readStream.on('error', (err: Error) => {
console.error(`स्ट्रीम त्रुटि पढ़ें: ${err.message}`);
});
writeStream.on('error', (err: Error) => {
console.error(`स्ट्रीम त्रुटि लिखें: ${err.message}`);
});
writeStream.on('finish', () => {
console.log(`फ़ाइल '\''${source}'\'' स्ट्रीम का उपयोग करके '\''${destination}'\'' में सफलतापूर्वक कॉपी की गई।`);
// कॉपी के बाद डमी बड़ी फ़ाइल को साफ करें
fs.unlink(largeFilePath, (err) => {
if (err) console.error('बड़ी फ़ाइल हटाने में त्रुटि:', err);
else console.log(`बड़ी फ़ाइल '\''${largeFilePath}'\'' हटाई गई।`);
});
});
}
// कॉपी करने का प्रयास करने से पहले बड़ी फ़ाइल बनने के लिए थोड़ी प्रतीक्षा करें
setTimeout(() => {
copyFileWithStreams(largeFilePath, copiedFilePath);
}, 1000);
परिवर्तनों के लिए देखना: `fs.watch`, `fs.watchFile`
फ़ाइल सिस्टम में परिवर्तनों की निगरानी हॉट-रीलोडिंग डेवलपमेंट सर्वर, बिल्ड प्रक्रियाओं या फ़ाइल सिस्टम के वास्तविक समय के डेटा सिंक्रनाइज़ेशन जैसे कार्यों के लिए महत्वपूर्ण है। Node.js इसके लिए दो प्राथमिक विधियाँ प्रदान करता है: `fs.watch` और `fs.watchFile`। टाइपस्क्रिप्ट यह सुनिश्चित करता है कि इवेंट प्रकार और श्रोता पैरामीटर सही ढंग से संभाले जाते हैं।
`fs.watch`: इवेंट-आधारित फ़ाइल सिस्टम वाचिंग
`fs.watch` आम तौर पर अधिक कुशल है क्योंकि यह अक्सर ऑपरेटिंग सिस्टम-स्तरीय सूचनाओं (उदा. लिनक्स पर `inotify`, macOS पर `kqueue`, विंडोज पर `ReadDirectoryChangesW`) का उपयोग करता है। यह परिवर्तनों, विलोपन या नाम बदलने के लिए विशिष्ट फ़ाइलों या डायरेक्टरीज़ की निगरानी के लिए उपयुक्त है।
import * as fs from 'fs';
const watchedFilePath: string = 'data/watched_file.txt';
const watchedDirPath: string = 'data/watched_dir';
// देखने के लिए फ़ाइलें/डायरेक्टरीज़ मौजूद सुनिश्चित करें
fs.writeFileSync(watchedFilePath, 'प्रारंभिक सामग्री।');
fs.mkdirSync(watchedDirPath, { recursive: true });
console.log(`परिवर्तनों के लिए '\''${watchedFilePath}'\'' देख रहा है...`);
const fileWatcher = fs.watch(watchedFilePath, (eventType: string, filename: string | Buffer | null) => {
const fname = typeof filename === 'string' ? filename : filename?.toString('utf8');
console.log(`फ़ाइल '\''${fname || 'N/A'}'\'' इवेंट: ${eventType}`);
if (eventType === 'change') {
console.log('फ़ाइल सामग्री संभावित रूप से बदल गई है।');
}
// एक वास्तविक एप्लिकेशन में, आप यहां फ़ाइल पढ़ सकते हैं या पुनर्निर्माण को ट्रिगर कर सकते हैं
});
console.log(`परिवर्तनों के लिए डायरेक्टरी '\''${watchedDirPath}'\'' देख रहा है...`);
const dirWatcher = fs.watch(watchedDirPath, (eventType: string, filename: string | Buffer | null) => {
const fname = typeof filename === 'string' ? filename : filename?.toString('utf8');
console.log(`डायरेक्टरी '\''${watchedDirPath}'\'' इवेंट: '${fname || 'N/A'}'\'' पर ${eventType}`);
});
fileWatcher.on('error', (err: Error) => console.error(`फ़ाइल वॉचर त्रुटि: ${err.message}`));
dirWatcher.on('error', (err: Error) => console.error(`डायरेक्टरी वॉचर त्रुटि: ${err.message}`));
// देरी के बाद परिवर्तनों का अनुकरण करें
setTimeout(() => {
console.log('\n--- परिवर्तनों का अनुकरण कर रहा है ---');
fs.appendFileSync(watchedFilePath, '\nनई पंक्ति जोड़ी गई।');
fs.writeFileSync(`${watchedDirPath}/new_file.txt`, 'सामग्री।');
fs.unlinkSync(`${watchedDirPath}/new_file.txt`); // विलोपन का भी परीक्षण करें
setTimeout(() => {
fileWatcher.close();
dirWatcher.close();
console.log('\nवॉचर्स बंद हो गए।');
// अस्थायी फ़ाइलों/डायरेक्टरीज़ को साफ करें
fs.unlinkSync(watchedFilePath);
fs.rmSync(watchedDirPath, { recursive: true, force: true });
}, 2000);
}, 1000);
`fs.watch` पर ध्यान दें: यह सभी प्रकार के इवेंट्स (उदा. फ़ाइल के नाम बदलने को विलोपन और निर्माण के रूप में रिपोर्ट किया जा सकता है) के लिए सभी प्लेटफ़ॉर्म पर हमेशा विश्वसनीय नहीं होता है। मजबूत क्रॉस-प्लेटफ़ॉर्म फ़ाइल वाचिंग के लिए, `chokidar` जैसी लाइब्रेरीज़ पर विचार करें, जो अक्सर `fs.watch` का उपयोग करती हैं लेकिन सामान्यीकरण और फ़ॉलबैक तंत्र जोड़ती हैं।
`fs.watchFile`: पोलिंग-आधारित फ़ाइल वाचिंग
`fs.watchFile` परिवर्तनों का पता लगाने के लिए पोलिंग (फ़ाइल के `stat` डेटा की समय-समय पर जाँच करना) का उपयोग करता है। यह कम कुशल है लेकिन विभिन्न फ़ाइल सिस्टम और नेटवर्क ड्राइव पर अधिक सुसंगत है। यह उन वातावरणों के लिए बेहतर अनुकूल है जहाँ `fs.watch` अविश्वसनीय हो सकता है (उदा. NFS शेयर)।
import * as fs from 'fs';
import { Stats } from 'fs';
const pollFilePath: string = 'data/polled_file.txt';
fs.writeFileSync(pollFilePath, 'प्रारंभिक मतदान की गई सामग्री।');
console.log(`परिवर्तनों के लिए '\''${pollFilePath}'\'' का मतदान कर रहा है...`);
fs.watchFile(pollFilePath, { interval: 1000 }, (curr: Stats, prev: Stats) => {
// टाइपस्क्रिप्ट सुनिश्चित करता है कि 'curr' और 'prev' fs.Stats ऑब्जेक्ट हैं
if (curr.mtimeMs !== prev.mtimeMs) {
console.log(`फ़ाइल '\''${pollFilePath}'\'' संशोधित (mtime बदला गया)। नया आकार: ${curr.size} बाइट्स।`);
}
});
setTimeout(() => {
console.log('\n--- मतदान की गई फ़ाइल परिवर्तन का अनुकरण कर रहा है ---');
fs.appendFileSync(pollFilePath, '\nमतदान की गई फ़ाइल में एक और पंक्ति जोड़ी गई।');
setTimeout(() => {
fs.unwatchFile(pollFilePath);
console.log(`\n'\''${pollFilePath}'\'' की निगरानी बंद कर दी गई।`);
fs.unlinkSync(pollFilePath);
}, 2000);
}, 1500);
वैश्विक संदर्भ में त्रुटि प्रबंधन और सर्वोत्तम प्रथाएँ
किसी भी उत्पादन-तैयार एप्लिकेशन के लिए मजबूत त्रुटि प्रबंधन सर्वोपरि है, खासकर जो फ़ाइल सिस्टम के साथ इंटरैक्ट करता है। फ़ाइल ऑपरेशंस कई कारणों से विफल हो सकते हैं: अनुमतियों की समस्याएँ, डिस्क पूर्ण त्रुटियाँ, फ़ाइल नहीं मिली, I/O त्रुटियाँ, नेटवर्क समस्याएँ (नेटवर्क-माउंटेड ड्राइव के लिए), या समवर्ती एक्सेस विरोध। टाइपस्क्रिप्ट आपको टाइप-संबंधित समस्याओं को पकड़ने में मदद करता है, लेकिन रनटाइम त्रुटियों को अभी भी सावधानीपूर्वक प्रबंधन की आवश्यकता है।
त्रुटि प्रबंधन रणनीतियाँ
- सिंक्रोनस ऑपरेशंस: हमेशा `try...catch` ब्लॉक में `fs.xxxSync` कॉल को रैप करें। ये विधियाँ सीधे त्रुटियाँ उत्पन्न करती हैं।
- एसिंक्रोनस कॉलबैक: `fs` कॉलबैक का पहला आर्गुमेंट हमेशा `err: NodeJS.ErrnoException | null` होता है। हमेशा इस `err` ऑब्जेक्ट की पहले जाँच करें।
- प्रॉमिस-आधारित (`fs/promises`): रिजेक्शन को संभालने के लिए `await` के साथ `try...catch` या `.then()` चेन्स के साथ `.catch()` का उपयोग करें।
त्रुटि लॉगिंग प्रारूपों को मानकीकृत करना और यदि आपके एप्लिकेशन की त्रुटि प्रतिक्रिया उपयोगकर्ता-सामने है तो त्रुटि संदेशों के लिए अंतर्राष्ट्रीयकरण (i18n) पर विचार करना फायदेमंद है।
import * as fs from 'fs';
import { promises as fsPromises } from 'fs';
import * as path from 'path';
const problematicPath = path.join('non_existent_dir', 'file.txt');
// सिंक्रोनस त्रुटि प्रबंधन
try {
fs.readFileSync(problematicPath, 'utf8');
} catch (error: any) {
console.error(`सिंक त्रुटि: ${error.code} - ${error.message} (पाथ: ${problematicPath})`);
}
// कॉलबैक-आधारित त्रुटि प्रबंधन
fs.readFile(problematicPath, 'utf8', (err, data) => {
if (err) {
console.error(`कॉलबैक त्रुटि: ${err.code} - ${err.message} (पाथ: ${problematicPath})`);
return;
}
// ... डेटा संसाधित करें
});
// प्रॉमिस-आधारित त्रुटि प्रबंधन
async function safeReadFile(filePath: string): Promise
संसाधन प्रबंधन: फ़ाइल डिस्क्रिप्टर बंद करना
`fs.open` (या `fsPromises.open`) के साथ काम करते समय, यह सुनिश्चित करना महत्वपूर्ण है कि फ़ाइल डिस्क्रिप्टर को ऑपरेशंस पूरा होने के बाद हमेशा `fs.close` (या `fileHandle.close()`) का उपयोग करके बंद किया जाए, भले ही त्रुटियाँ क्यों न हों। ऐसा करने में विफल रहने से संसाधन लीक हो सकते हैं, ऑपरेटिंग सिस्टम की खुली फ़ाइल सीमा तक पहुँच सकते हैं, और संभावित रूप से आपके एप्लिकेशन को क्रैश कर सकते हैं या अन्य प्रक्रियाओं को प्रभावित कर सकते हैं।
`FileHandle` ऑब्जेक्ट्स के साथ `fs/promises` एपीआई आम तौर पर इसे सरल बनाता है, क्योंकि `fileHandle.close()` विशेष रूप से इस उद्देश्य के लिए डिज़ाइन किया गया है, और `FileHandle` इंस्टेंसेस `Disposable` हैं (यदि Node.js 18.11.0+ और टाइपस्क्रिप्ट 5.2+ का उपयोग कर रहे हैं)।
पाथ प्रबंधन और क्रॉस-प्लेटफ़ॉर्म संगतता
फ़ाइल पाथ ऑपरेटिंग सिस्टम के बीच काफी भिन्न होते हैं (उदा. विंडोज पर `\`, यूनिक्स-जैसे सिस्टम पर `/`)। Node.js `path` मॉड्यूल क्रॉस-प्लेटफ़ॉर्म संगत तरीके से फ़ाइल पाथ बनाने और पार्स करने के लिए अपरिहार्य है, जो वैश्विक तैनाती के लिए आवश्यक है।
- `path.join(...paths)`: दिए गए सभी पाथ सेगमेंट को एक साथ जोड़ता है, जिससे परिणामी पाथ सामान्य हो जाता है।
- `path.resolve(...paths)`: पाथ या पाथ सेगमेंट के अनुक्रम को एक पूर्ण पाथ में हल करता है।
- `path.basename(path)`: पाथ का अंतिम भाग लौटाता है।
- `path.dirname(path)`: पाथ का डायरेक्टरी नाम लौटाता है।
- `path.extname(path)`: पाथ का एक्सटेंशन लौटाता है।
टाइपस्क्रिप्ट `path` मॉड्यूल के लिए पूर्ण टाइप परिभाषाएँ प्रदान करता है, जिससे यह सुनिश्चित होता है कि आप इसके फ़ंक्शंस का सही ढंग से उपयोग करते हैं।
import * as path from 'path';
const dir = 'my_app_data';
const filename = 'config.json';
// क्रॉस-प्लेटफ़ॉर्म पाथ जॉइनिंग
const fullPath: string = path.join(__dirname, dir, filename);
console.log(`क्रॉस-प्लेटफ़ॉर्म पाथ: ${fullPath}`);
// डायरेक्टरी नाम प्राप्त करें
const dirname: string = path.dirname(fullPath);
console.log(`डायरेक्टरी नाम: ${dirname}`);
// बेस फ़ाइल नाम प्राप्त करें
const basename: string = path.basename(fullPath);
console.log(`बेस नाम: ${basename}`);
// फ़ाइल एक्सटेंशन प्राप्त करें
const extname: string = path.extname(fullPath);
console.log(`एक्सटेंशन: ${extname}`);
समवर्तीता और दौड़ की स्थिति
जब कई एसिंक्रोनस फ़ाइल ऑपरेशंस समवर्ती रूप से शुरू किए जाते हैं, खासकर राइट्स या विलोपन, तो दौड़ की स्थिति उत्पन्न हो सकती है। उदाहरण के लिए, यदि एक ऑपरेशन किसी फ़ाइल के अस्तित्व की जाँच करता है और दूसरा ऑपरेशन पहले ऑपरेशन के कार्य करने से पहले उसे हटा देता है, तो पहला ऑपरेशन अप्रत्याशित रूप से विफल हो सकता है।
- महत्वपूर्ण पाथ लॉजिक के लिए `fs.existsSync` से बचें; `fs.access` को प्राथमिकता दें या बस ऑपरेशन का प्रयास करें और त्रुटि को संभालें।
- विशेष एक्सेस की आवश्यकता वाले ऑपरेशंस के लिए, उपयुक्त `flag` विकल्पों का उपयोग करें (उदा. एक्सक्लूसिव राइट के लिए `'wx'`)।
- अत्यधिक महत्वपूर्ण साझा संसाधन एक्सेस के लिए लॉकिंग तंत्र (उदा. फ़ाइल लॉक, या एप्लिकेशन-स्तरीय लॉक) लागू करें, हालांकि इससे जटिलता बढ़ जाती है।
अनुमतियाँ (ACLs)
फ़ाइल सिस्टम अनुमतियाँ (एक्सेस कंट्रोल लिस्ट्स या मानक यूनिक्स अनुमतियाँ) त्रुटियों का एक सामान्य स्रोत हैं। सुनिश्चित करें कि आपके Node.js प्रक्रिया के पास फ़ाइलों और डायरेक्टरीज़ को पढ़ने, लिखने या निष्पादित करने के लिए आवश्यक अनुमतियाँ हैं। यह कंटेनराइज़्ड वातावरण में या बहु-उपयोगकर्ता सिस्टम पर विशेष रूप से प्रासंगिक है जहाँ प्रक्रियाएँ विशिष्ट उपयोगकर्ता खातों के साथ चलती हैं।
निष्कर्ष: वैश्विक फ़ाइल सिस्टम ऑपरेशंस के लिए टाइप सुरक्षा को अपनाना
Node.js `fs` मॉड्यूल फ़ाइल सिस्टम के साथ इंटरैक्ट करने के लिए एक शक्तिशाली और बहुमुखी उपकरण है, जो बुनियादी फ़ाइल हेरफेर से लेकर उन्नत स्ट्रीम-आधारित डेटा प्रोसेसिंग तक विकल्पों का एक स्पेक्ट्रम प्रदान करता है। इन ऑपरेशंस के शीर्ष पर टाइपस्क्रिप्ट की परत लगाने से, आपको अमूल्य लाभ मिलते हैं: कंपाइल-टाइम त्रुटि का पता लगाना, बढ़ी हुई कोड स्पष्टता, बेहतर टूलिंग समर्थन और रिफैक्टरिंग के दौरान बढ़ा हुआ आत्मविश्वास। यह वैश्विक विकास टीमों के लिए विशेष रूप से महत्वपूर्ण है जहां विविध कोडबेसों में निरंतरता और कम अस्पष्टता महत्वपूर्ण है।
चाहे आप एक छोटी उपयोगिता स्क्रिप्ट बना रहे हों या एक बड़े पैमाने पर एंटरप्राइज़ एप्लिकेशन, अपने Node.js फ़ाइल ऑपरेशंस के लिए टाइपस्क्रिप्ट के मजबूत टाइप सिस्टम का लाभ उठाने से अधिक रखरखाव योग्य, विश्वसनीय और त्रुटि-प्रतिरोधी कोड प्राप्त होगा। क्लीनर एसिंक्रोनस पैटर्न के लिए `fs/promises` एपीआई को अपनाएं, सिंक्रोनस और एसिंक्रोनस कॉल के बीच की बारीकियों को समझें, और हमेशा मजबूत त्रुटि प्रबंधन और क्रॉस-प्लेटफ़ॉर्म पाथ प्रबंधन को प्राथमिकता दें।
इस गाइड में चर्चा किए गए सिद्धांतों और उदाहरणों को लागू करके, दुनिया भर के डेवलपर्स फ़ाइल सिस्टम इंटरैक्शन बना सकते हैं जो न केवल प्रदर्शनकारी और कुशल हैं बल्कि स्वाभाविक रूप से अधिक सुरक्षित और तर्क करने में आसान हैं, अंततः उच्च गुणवत्ता वाले सॉफ्टवेयर डिलिवरेबल्स में योगदान करते हैं।